/*
* Copyright (c) 2011-2015 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.spotify.google.cloud.pubsub.client.integration;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.pubsub.PubsubScopes;
import com.google.common.util.concurrent.Futures;
import com.spotify.google.cloud.pubsub.client.Message;
import com.spotify.google.cloud.pubsub.client.Publisher;
import com.spotify.google.cloud.pubsub.client.Pubsub;
import com.spotify.logging.LoggingConfigurator;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
import java.util.zip.Deflater;
import static com.spotify.google.cloud.pubsub.client.integration.Util.TEST_NAME_PREFIX;
import static com.spotify.google.cloud.pubsub.client.integration.Util.nonGcmCiphers;
import static com.spotify.logging.LoggingConfigurator.Level.WARN;
import static java.util.stream.Collectors.toList;
public class PublisherBenchmark {
private static final int MESSAGE_SIZE = 512;
public static void main(final String... args) throws IOException {
final String project = Util.defaultProject();
GoogleCredential credential;
// Use credentials from file if available
try {
credential = GoogleCredential
.fromStream(new FileInputStream("credentials.json"))
.createScoped(PubsubScopes.all());
} catch (IOException e) {
credential = GoogleCredential.getApplicationDefault()
.createScoped(PubsubScopes.all());
}
final Pubsub pubsub = Pubsub.builder()
.credential(credential)
.compressionLevel(Deflater.BEST_SPEED)
.enabledCipherSuites(nonGcmCiphers())
.build();
final Publisher publisher = Publisher.builder()
.pubsub(pubsub)
.concurrency(128)
.project(project)
.build();
LoggingConfigurator.configureDefaults("benchmark", WARN);
final String topicPrefix = TEST_NAME_PREFIX + ThreadLocalRandom.current().nextInt();
final List<String> topics = IntStream.range(0, 100)
.mapToObj(i -> topicPrefix + "-" + i)
.collect(toList());
topics.stream()
.map(topic -> pubsub.createTopic(project, topic))
.collect(toList())
.forEach(Futures::getUnchecked);
final List<Message> messages = IntStream.range(0, 1000)
.mapToObj(i -> {
final StringBuilder s = new StringBuilder();
while (s.length() < MESSAGE_SIZE) {
s.append(ThreadLocalRandom.current().nextInt());
}
return Message.ofEncoded(s.toString());
})
.collect(toList());
final ProgressMeter meter = new ProgressMeter();
final ProgressMeter.Metric requests = meter.group("operations").metric("publishes", "messages");
for (int i = 0; i < 100000; i++) {
benchSend(publisher, messages, topics, requests);
}
}
private static void benchSend(final Publisher publisher, final List<Message> messages,
final List<String> topics, final ProgressMeter.Metric requests) {
final String topic = topics.get(ThreadLocalRandom.current().nextInt(topics.size()));
final Message message = messages.get(ThreadLocalRandom.current().nextInt(messages.size()));
final CompletableFuture<String> future = publisher.publish(topic, message);
final long start = System.nanoTime();
future.whenComplete((s, ex) -> {
if (ex != null) {
ex.printStackTrace();
return;
}
final long end = System.nanoTime();
final long latency = end - start;
requests.inc(latency);
benchSend(publisher, messages, topics, requests);
});
}
}